# coding=utf-8
from __future__ import unicode_literals
import datetime

import requests
from lxml import etree
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from model import (StockFlowModel, ThemeFlowModel)

from config import (logging, Config)
from trade_date import get_trade_calendar


class FundFlow(object):
    # 同花顺数据中心-资金流数据采集

    engine = create_engine(Config.MYSQL_URL, echo=False)
    DBSession = sessionmaker(bind=engine)
    db_session = DBSession()

    def __init__(self):
        self.date = None                # 日期

    def get_theme_fund_flow(self):
        """ 获取概念、行业资金流 """

        # 获取概念资金流
        page_max = 4  # 最大页数
        for page_num in xrange(1, page_max+1):
            page_url = ('http://data.10jqka.com.cn/funds/gnzjl/field/'
                        'tradezdf/order/desc/page/{0}/ajax/1/'.format(page_num))
            response = requests.get(page_url)
            self.extract_theme_page(response.text, fund_type=1)
        self.db_session.commit()
        logging.info('Finish-获取概念资金流')
        # 获取行业资金流
        page_max = 2  # 最大页数
        for page_num in xrange(1, page_max+1):
            page_url = ('http://data.10jqka.com.cn/funds/hyzjl/field/'
                        'tradezdf/order/desc/page/{0}/ajax/1/'.format(page_num))
            response = requests.get(page_url)
            self.extract_theme_page(response.text, fund_type=2)
        self.db_session.commit()
        logging.info('Finish-获取行业资金流')

    def extract_theme_page(self, text, fund_type):
        """ 提取概念/行业页面内容，并保存
        :param text: response.text
        :param fund_type: 1表示概念，2表示行业
        :return: None
        """
        selector = etree.HTML(text)
        elements = selector.xpath('//table[@class="m-table J-ajax-table"]/tbody/tr')
        for element in elements:
            name = element.xpath('.//td[2]/a/text()')[0]  # 概念名称
            index = float(element.xpath('.//td[3]/text()')[0])  # 行业指数
            rose_ratio = float(element.xpath('.//td[4]/text()')[0].rstrip('%'))  # 涨跌幅
            fund_amount_in = float(element.xpath('.//td[5]/text()')[0])   # 流入资金
            fund_amount_out = float(element.xpath('.//td[6]/text()')[0])  # 流出资金
            fund_real_in = float(element.xpath('.//td[7]/text()')[0])  # 净额
            company_num = int(element.xpath('.//td[8]/text()')[0])  # 公司家数
            leader = element.xpath('.//td[9]/a/text()')[0]  # 领涨股
            leader_rose_ratio = float(element.xpath('.//td[10]/text()')[0].rstrip('%'))  # 涨跌幅
            leader_price = float(element.xpath('.//td[11]/text()')[0])  # 当前价
            theme_fund = ThemeFlowModel(date=self.date, name=name, index=index,
                                        rose_ratio=rose_ratio, fund_amount_out=fund_amount_out,
                                        fund_amount_in=fund_amount_in, fund_real_in=fund_real_in,
                                        company_num=company_num, leader=leader, leader_rose_ratio=leader_rose_ratio,
                                        leader_price=leader_price, fund_type=fund_type)
            self.db_session.add(theme_fund)

    def get_stock_fund_flow(self):
        """ 获取个股资金流 """
        page_max = 63  # 最大页数
        for page_num in xrange(1, page_max+1):
            page_url = 'http://data.10jqka.com.cn/funds/ggzjl/field/zdf/order/desc/page/{0}/ajax/1/'.format(page_num)
            response = requests.get(page_url)
            self.extract_stock_page(response.text)
        self.db_session.commit()
        logging.info('Finish-获取个股资金流')

    def extract_stock_page(self, text):
        """ 提取个股页面内容, 并保存
        :param text: response.text 
        :return: None
        """
        selector = etree.HTML(text)
        elements = selector.xpath('//table[@class="m-table J-ajax-table"]/tbody/tr')
        for element in elements:
            symbol = element.xpath('.//td[2]/a/text()')[0]                              # 代码
            name = element.xpath('.//td[3]/a/text()')[0]                                # 名称
            price = float(element.xpath('.//td[4]/text()')[0])                          # 最新价格
            rose_ratio = float(element.xpath('.//td[5]/text()')[0].rstrip('%'))         # 涨跌幅
            hand_ratio = float(element.xpath('.//td[6]/text()')[0].rstrip('%'))         # 换手率
            fund_amount_in = self.handle_data(element.xpath('.//td[7]/text()')[0])      # 流入资金
            fund_amount_out = self.handle_data(element.xpath('.//td[8]/text()')[0])     # 流出资金
            fund_real_in = self.handle_data(element.xpath('.//td[9]/text()')[0])        # 净额
            trade_amount = self.handle_data(element.xpath('.//td[10]/text()')[0])       # 成交额
            big_trade_in = self.handle_data(element.xpath('.//td[11]/text()')[0])       # 大单流入
            stock_fund = StockFlowModel(date=self.date, symbol=symbol, name=name, price=price,
                                        rose_ratio=rose_ratio, hand_ratio=hand_ratio, fund_amount_in=fund_amount_in,
                                        fund_amount_out=fund_amount_out, fund_real_in=fund_real_in,
                                        trade_amount=trade_amount, big_trade_in=big_trade_in)
            self.db_session.add(stock_fund)

    @staticmethod
    def handle_data(text):
        """ 统一个股页面单位表示，全部转为万
        :param text: 字符串
        :return: float
        """
        text = text.strip()
        if '亿' in text:
            text = text.rstrip('亿')
            text = float(text) * 10000
        elif '万' in text:
            text = text.rstrip('万')
        return float(text)

    def run(self):
        """ 触发函数 """
        try:
            logging.info('提示-启动同花顺资金流爬虫')
            trade_calendar = get_trade_calendar()
            str_today = str(datetime.date.today())
            if str_today not in trade_calendar:
                logging.info('警告-当天非交易日')
                return
            else:
                self.date = str_today
                self.get_theme_fund_flow()
                self.get_stock_fund_flow()
                logging.info('提示-完成资金流数据获取：{0}的获取'.format(self.date))
        except (KeyError, IndexError):
            logging.exception('异常')
        finally:
            FundFlow.db_session.close()   # 关闭连接

if __name__ == '__main__':
    host = FundFlow()
    host.run()
